home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / wgdb-42.lha / wgdb-4.2 / gdb / exec.c < prev    next >
C/C++ Source or Header  |  1992-09-11  |  11KB  |  382 lines

  1. /* Work with executable files, for GDB. 
  2.    Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include "defs.h"
  22. #include "param.h"
  23. #include "frame.h"
  24. #include "inferior.h"
  25. #include "target.h"
  26. #include "gdbcmd.h"
  27.  
  28. #ifdef USG
  29. #include <sys/types.h>
  30. #endif
  31.  
  32. #include <sys/param.h>
  33. #include <fcntl.h>
  34. #include <string.h>
  35.  
  36. #include "gdbcore.h"
  37.  
  38. #include <ctype.h>
  39. #include <sys/stat.h>
  40.  
  41. extern char *getenv();
  42. extern void child_create_inferior (), child_attach ();
  43. extern void symbol_file_command ();
  44.  
  45. /* The Binary File Descriptor handle for the executable file.  */
  46.  
  47. bfd *exec_bfd = NULL;
  48.  
  49. /* Whether to open exec and core files read-only or read-write.  */
  50.  
  51. int write_files = 0;
  52.  
  53. /* Text start and end addresses (KLUDGE) if needed */
  54.  
  55. #ifdef NEED_TEXT_START_END
  56. CORE_ADDR text_start = 0;
  57. CORE_ADDR text_end   = 0;
  58. #endif
  59.  
  60. /* Forward decl */
  61.  
  62. extern struct target_ops exec_ops;
  63.  
  64. /* ARGSUSED */
  65. void
  66. exec_close (quitting)
  67.      int quitting;
  68. {
  69.   if (exec_bfd) {
  70.     bfd_close (exec_bfd);
  71.     exec_bfd = NULL;
  72.   }
  73.   if (exec_ops.sections) {
  74.     free (exec_ops.sections);
  75.     exec_ops.sections = NULL;
  76.     exec_ops.sections_end = NULL;
  77.   }
  78. }
  79.  
  80. void
  81. exec_file_command (filename, from_tty)
  82.      char *filename;
  83.      int from_tty;
  84. {
  85.   target_preopen (from_tty);
  86.  
  87.   /* Remove any previous exec file.  */
  88.   unpush_target (&exec_ops);
  89.  
  90.   /* Now open and digest the file the user requested, if any.  */
  91.  
  92.   if (filename)
  93.     {
  94.       char *scratch_pathname;
  95.       int scratch_chan;
  96.       
  97.       filename = tilde_expand (filename);
  98.       make_cleanup (free, filename);
  99.       
  100.       scratch_chan = openp (getenv ("PATH"), 1, filename, 
  101.                 write_files? O_RDWR: O_RDONLY, 0,
  102.                 &scratch_pathname);
  103.       if (scratch_chan < 0)
  104.     perror_with_name (filename);
  105.  
  106.       exec_bfd = bfd_fdopenr (scratch_pathname, NULL, scratch_chan);
  107.       if (!exec_bfd)
  108.     error ("Could not open `%s' as an executable file: %s",
  109.            scratch_pathname, bfd_errmsg (bfd_error));
  110.       if (!bfd_check_format (exec_bfd, bfd_object))
  111.     error ("\"%s\": not in executable format: %s.",
  112.            scratch_pathname, bfd_errmsg (bfd_error));
  113.  
  114.       if (build_section_table (exec_bfd, &exec_ops.sections,
  115.                 &exec_ops.sections_end))
  116.     error ("Can't find the file sections in `%s': %s", 
  117.         exec_bfd->filename, bfd_errmsg (bfd_error));
  118.  
  119. #ifdef NEED_TEXT_START_END
  120.       /* This is a KLUDGE (FIXME) because a few places in a few ports
  121.      (29K springs to mind) need this info for now.  */
  122.       {
  123.     struct section_table *p;
  124.     for (p = exec_ops.sections; p < exec_ops.sections_end; p++)
  125.       if (!strcmp (".text", bfd_section_name (p->bfd, p->sec_ptr)))
  126.         {
  127.           text_start = p->addr;
  128.           text_end   = p->endaddr;
  129.           break;
  130.         }
  131.       }
  132. #endif
  133.  
  134.       validate_files ();
  135.  
  136.       push_target (&exec_ops);
  137.  
  138.       /* Tell display code (if any) about the changed file name.  */
  139.       if (exec_file_display_hook)
  140.     (*exec_file_display_hook) (filename);
  141.     }
  142.   else if (from_tty)
  143.     printf ("No exec file now.\n");
  144. }
  145.  
  146. /* Set both the exec file and the symbol file, in one command.  
  147.    What a novelty.  Why did GDB go through four major releases before this
  148.    command was added?  */
  149.  
  150. void
  151. file_command (arg, from_tty)
  152.      char *arg;
  153.      int from_tty;
  154. {
  155.   /* FIXME, if we lose on reading the symbol file, we should revert
  156.      the exec file, but that's rough.  */
  157.   exec_file_command (arg, from_tty);
  158.   symbol_file_command (arg, from_tty);
  159. }
  160.  
  161.  
  162. /* Locate all mappable sections of a BFD file. 
  163.    table_pp_char is a char * to get it through bfd_map_over_sections;
  164.    we cast it back to its proper type.  */
  165.  
  166. void
  167. add_to_section_table (abfd, asect, table_pp_char)
  168.      bfd *abfd;
  169.      sec_ptr asect;
  170.      char *table_pp_char;
  171. {
  172.   struct section_table **table_pp = (struct section_table **)table_pp_char;
  173.   flagword aflag;
  174.  
  175.   aflag = bfd_get_section_flags (abfd, asect);
  176.   /* FIXME, we need to handle BSS segment here...it alloc's but doesn't load */
  177.   if (!(aflag & SEC_LOAD))
  178.     return;
  179.   if (0 == bfd_section_size (abfd, asect))
  180.     return;
  181.   (*table_pp)->bfd = abfd;
  182.   (*table_pp)->sec_ptr = asect;
  183.   (*table_pp)->addr = bfd_section_vma (abfd, asect);
  184.   (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect);
  185.   (*table_pp)++;
  186. }
  187.  
  188. int
  189. build_section_table (some_bfd, start, end)
  190.      bfd *some_bfd;
  191.      struct section_table **start, **end;
  192. {
  193.   unsigned count;
  194.  
  195.   count = bfd_count_sections (some_bfd);
  196.   if (count == 0)
  197.     abort();    /* return 1? */
  198.   if (*start)
  199.     free (*start);
  200.   *start = (struct section_table *) xmalloc (count * sizeof (**start));
  201.   *end = *start;
  202.   bfd_map_over_sections (some_bfd, add_to_section_table, (char *)end);
  203.   if (*end > *start + count)
  204.     abort();
  205.   /* We could realloc the table, but it probably loses for most files.  */
  206.   return 0;
  207. }
  208.  
  209. /* Read or write the exec file.
  210.  
  211.    Args are address within a BFD file, address within gdb address-space,
  212.    length, and a flag indicating whether to read or write.
  213.  
  214.    Result is a length:
  215.  
  216.     0:    We cannot handle this address and length.
  217.     > 0:  We have handled N bytes starting at this address.
  218.           (If N == length, we did it all.)  We might be able
  219.           to handle more bytes beyond this length, but no
  220.           promises.
  221.     < 0:  We cannot handle this address, but if somebody
  222.           else handles (-N) bytes, we can start from there.
  223.  
  224.     The same routine is used to handle both core and exec files;
  225.     we just tail-call it with more arguments to select between them.  */
  226.  
  227. int
  228. xfer_memory (memaddr, myaddr, len, write, target)
  229.      CORE_ADDR memaddr;
  230.      char *myaddr;
  231.      int len;
  232.      int write;
  233.      struct target_ops *target;
  234. {
  235.   boolean res;
  236.   struct section_table *p;
  237.   CORE_ADDR nextsectaddr, memend;
  238.   boolean (*xfer_fn) ();
  239.  
  240.   if (len <= 0)
  241.     abort();
  242.  
  243.   memend = memaddr + len;
  244.   xfer_fn = write? bfd_set_section_contents: bfd_get_section_contents;
  245.   nextsectaddr = memend;
  246.  
  247.   for (p = target->sections; p < target->sections_end; p++)
  248.     {
  249.       if (p->addr <= memaddr)
  250.     if (p->endaddr >= memend)
  251.       {
  252.         /* Entire transfer is within this section.  */
  253.         res = xfer_fn (p->bfd, p->sec_ptr, myaddr, memaddr - p->addr, len);
  254.         return (res != false)? len: 0;
  255.       }
  256.     else if (p->endaddr <= memaddr)
  257.       {
  258.         /* This section ends before the transfer starts.  */
  259.         continue;
  260.       }
  261.     else 
  262.       {
  263.         /* This section overlaps the transfer.  Just do half.  */
  264.         len = p->endaddr - memaddr;
  265.         res = xfer_fn (p->bfd, p->sec_ptr, myaddr, memaddr - p->addr, len);
  266.         return (res != false)? len: 0;
  267.       }
  268.       else if (p->addr < nextsectaddr)
  269.     nextsectaddr = p->addr;
  270.     }
  271.  
  272.   if (nextsectaddr >= memend)
  273.     return 0;                /* We can't help */
  274.   else
  275.     return - (nextsectaddr - memaddr);    /* Next boundary where we can help */
  276. }
  277.  
  278. #ifdef FIXME
  279. #ifdef REG_STACK_SEGMENT
  280. /* MOVE TO BFD... */
  281.     /* Pyramids and AM29000s have an extra segment in the virtual address space
  282.        for the (control) stack of register-window frames.  The AM29000 folk
  283.        call it the "register stack" rather than the "memory stack".  */
  284.     else if (memaddr >= reg_stack_start && memaddr < reg_stack_end)
  285.       {
  286.     i = min (len, reg_stack_end - memaddr);
  287.     fileptr = memaddr - reg_stack_start + reg_stack_offset;
  288.     wanna_xfer = coredata;
  289.       }
  290. #endif                /* REG_STACK_SEGMENT */
  291. #endif FIXME
  292.  
  293. static void
  294. exec_files_info ()
  295. {
  296.   struct section_table *p;
  297.  
  298.   printf ("\tExecutable file `%s'.\n", bfd_get_filename(exec_bfd));
  299.  
  300.   for (p = exec_ops.sections; p < exec_ops.sections_end; p++) {
  301.     printf("\t%s", local_hex_string_custom (p->addr, "08"));
  302.     printf(" - %s is %s\n", local_hex_string_custom (p->endaddr, "08"),
  303.     bfd_section_name (exec_bfd, p->sec_ptr));
  304.   }
  305. }
  306.  
  307. static void
  308. set_section_command (args, from_tty)
  309.      char *args;
  310.      int from_tty;
  311. {
  312.   struct section_table *p;
  313.   char *secname;
  314.   unsigned seclen;
  315.   unsigned long secaddr;
  316.   char secprint[100];
  317.   long offset;
  318.  
  319.   if (args == 0)
  320.     error ("Must specify section name and its virtual address");
  321.  
  322.   /* Parse out section name */
  323.   for (secname = args; !isspace(*args); args++) ;
  324.   seclen = args - secname;
  325.  
  326.   /* Parse out new virtual address */
  327.   secaddr = parse_and_eval_address (args);
  328.  
  329.   for (p = exec_ops.sections; p < exec_ops.sections_end; p++) {
  330.     if (!strncmp (secname, bfd_section_name (exec_bfd, p->sec_ptr), seclen)
  331.     && bfd_section_name (exec_bfd, p->sec_ptr)[seclen] == '\0') {
  332.       offset = secaddr - p->addr;
  333.       p->addr += offset;
  334.       p->endaddr += offset;
  335.       exec_files_info();
  336.       return;
  337.     }
  338.   } 
  339.   if (seclen >= sizeof (secprint))
  340.     seclen = sizeof (secprint) - 1;
  341.   strncpy (secprint, secname, seclen);
  342.   secprint[seclen] = '\0';
  343.   error ("Section %s not found", secprint);
  344. }
  345.  
  346. struct target_ops exec_ops = {
  347.     "exec", "Local exec file",
  348.     "Use an executable file as a target.\n\
  349. Specify the filename of the executable file.",
  350.     exec_file_command, exec_close, /* open, close */
  351.     child_attach, 0, 0, 0, /* attach, detach, resume, wait, */
  352.     0, 0, /* fetch_registers, store_registers, */
  353.     0, 0, 0, /* prepare_to_store, conv_to, conv_from, */
  354.     xfer_memory, exec_files_info,
  355.     0, 0, /* insert_breakpeIirtual address");
  356.  
  357.   /* Pope: 0, 0, /* pre/* insert*/
  358. en,c fstuff, 0, /* fetch_kill,*/
  359.   if ( /* fetch_t thefn,*/
  360. okee,_fihild_attachcIires     0,erior0, /* ch_mjorn     0,eriorhild_omman taatum* fetch_ctadif ( /* 1* pre/* inG_STppablem,blem,boffsestacks_filesif ( /* feREG_STn name ** Pop/
  361.     if ( OPS_MAGIC,EG_STAlwaytransfla file thi#ifd;
  362. add_to     0itie_fznd (ec struag =dt_seend"
  363.     "Use */ass_info,name, nd, exec_res =n exeFILEtarges.g  Tlecte
  364.     debugle pecifI lengr wriecnartua_file_,namcna\
  365. Ste symbolts;
  366.   nee expucan, exec_ecifs virtlengmboles.g  Tlable fg swe n youto hgmbol`run'nd.  
  367.    ecifIfeFILEt handlebe", sectargy sectiec_cyjor able fme *dansctack"me, ecif($, 1,) tion arforriecnaand was ad execs a */
  368.  ecifc f\n\n, .  ndle bv\n")table file as a tanopena_file_,. /* Par=dt_seend"able-
  369.     "Use */ass_info,naile_command, exec_res =n exeFILEtarges.g  Tlmcna\
  370. Ste syts;
  371.   nee expucan, exec ecifIfeFILEt handlebe", sectargy sectiec_cyjor able fme *dansctack"me, eciftion arforriecnaand was ad execs a */
  372.  ecifc f\n\n, .  n bv\n")table file as a . /* Par=dt_seend"n name se */ass_info,naction_command (argsength"C filegmbolbasess within exn name *AD)TIONe executableas a tdleexts ecifectiolp *be"o haniexecutableas a tt loound"ts;
  373. an, n name *s withio,necif(suchtarg virtuaa.w viecnmatlente.
  374. hevirtuaa withio,gy sectiecg virtuecifs a trtuelfddreswrfse   Eesu n name *mecifbged file nsto_sresly AM290ecif``or nownfo,''nd.  
  375.    l, *sTppabmbol s (some_e symboiraa withio,. /* Par=dt_ rew */
  376.     ectieclen(=dt_  excms, " bfd_se */ass_sup     (2,ater_n (*xfer *)end);
  377. & bfd__info,n
  378.     es "th t bfde syPop)table file ae synd ex  */
  379.  "n
  380.     es &  el, *), retur& rewl, *)ror Par=dt_ (&exec_ops);
  381.  
  382.